<?php
// +----------------------------------------------------------------------
// | XML工具库
// +----------------------------------------------------------------------

namespace helper\util;

use DOMDocument;
use SimpleXMLElement;
use XMLReader;
use XMLWriter;

class DocumentBuilder
{
    public function loadFile($url)
    {
        return simplexml_load_file($url);
    }

    /**
     * xml转成数组
     * @param $xmlStr string
     * @return array
     */
    public function toArray($xmlStr)
    {
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $xmlString = simplexml_load_string($xmlStr, 'SimpleXMLElement', LIBXML_NOCDATA);
        return json_decode(json_encode($xmlString), true);
    }

    function arrToXml($data, $eIsArray = FALSE)
    {
        $xml = new XmlWriter();
        if (!$eIsArray) {
            $xml->openMemory();
            $xml->startDocument('1.0', 'UTF-8');
            $xml->startElement('root');
        }
        foreach ($data as $key => $value) {
            if (is_array($value)) {
                $xml->startElement($key);
                $this->arrToXml($value, TRUE);
                $xml->endElement();
                continue;
            }
            $xml->writeElement($key, $value);
        }
        if (!$eIsArray) {
            $xml->endElement();
            return $xml->outputMemory(true);
        }
    }

    public function list($xml)
    {
        /**
         * <?xml version="1.0" encoding="UTF-8"?>
         * <books>
         * <book id="1" category="c程序设计">
         * <imgpic>images/1.jpg</imgpic>
         * <title>c语言程序设计</title>
         * <author>韩顺平</author>
         * <pubdate>2010-1-11</pubdate>
         * <isbn>2010-1-11</isbn>
         * <price>10.00</price>
         * </book>
         * </books>
         */

        //初始化domdocument类
        $xmldoc = new DOMDocument('1.0', "UTF-8");
        //载入XML文档
        $xmldoc->load($xml);
        //获取节点
        $books = $xmldoc->getElementsByTagName("book");

        //通过DOMNodeList里面的length属性来获取图书的数量
        $id = $books->length + 1;
        for ($i = 0; $i < $books->length; $i++) {
            echo $books->item($i)->getAttribute("id");
            echo $books->item($i)->getElementsByTagName("title")->item(0)->nodeValue;
        }
    }

    public function sync()
    {
        $act = $_REQUEST['act'];

        if ($act == 'add') {
            $id = $_POST['id'];
            $category = $_POST['category'];
            $imgpicval = $_POST['imgpic'];
            $titleval = $_POST['title'];
            $authorval = $_POST['author'];
            $pubdateval = $_POST['pubdate'];
            $isbnval = $_POST['isbn'];
            $priceval = $_POST['price'];

            //echo $id.$category.$title.$author.$pubdate.$isbn.$price;
            //初始化
            $xmldoc = new DOMDocument();
            $xmldoc->load("library.xml");

            //获取父节点（根节点）
            $books = $xmldoc->getElementsByTagName("books")->item(0);

            //创建要添加子节点
            $book = $xmldoc->createElement("book");

            $book->setAttribute('id', $id);
            $book->setAttribute('category', $category);

            //创建一个<imgpic>的子节点
            $imgpic = $xmldoc->createElement("imgpic");
            $imgpic->nodeValue = $imgpicval;
            //追加imgpic节点到book节点
            $book->appendChild($imgpic);

            //创建一个<titile>的子节点
            $title = $xmldoc->createElement("title");
            $title->nodeValue = $titleval;
            //追加title节点到book节点
            $book->appendChild($title);

            //创建一个<titile>的子节点
            $author = $xmldoc->createElement("author");
            $author->nodeValue = $authorval;
            //追加title节点到book节点
            $book->appendChild($author);

            //创建一个<titile>的子节点
            $pubdate = $xmldoc->createElement("pubdate");
            $pubdate->nodeValue = $pubdateval;
            //追加title节点到book节点
            $book->appendChild($pubdate);

            //创建一个<titile>的子节点
            $isbn = $xmldoc->createElement("isbn");
            $isbn->nodeValue = $isbnval;
            //追加title节点到book节点
            $book->appendChild($isbn);

            //创建一个<titile>的子节点
            $price = $xmldoc->createElement("price");
            $price->nodeValue = $priceval;
            //追加title节点到book节点
            $book->appendChild($price);

            //追加$book子节点到$books根节点
            $books->appendChild($book);

            $xmldoc->save("library.xml");
            echo "<script language='javascript'>alert('添加成功');location.href='index.php';</script>";
        } elseif ($act == "del") {
            $id = $_GET['id'] - 1;

            //初始化domdocument类
            $xmldoc = new DOMDocument('1.0', "UTF-8");
            //载入XML文档
            $xmldoc->load("library.xml");
            //获取根节点
            $root = $xmldoc->getElementsByTagName("books")->item(0);
            //获取book节点
            $books = $xmldoc->getElementsByTagName("book");
            //查找我要删除的节点
            $book = $books->item($id);
            //节点删除
            $root->removeChild($book);
            //保存
            $xmldoc->save("library.xml");
            echo "<script language='javascript'>alert('删除成功');location.href='index.php';</script>";
        } elseif ($act == 'update') {
            $id = $_POST['id'];
            $category = $_POST['category'];
            $imgpicval = $_POST['imgpic'];
            $titleval = $_POST['title'];
            $authorval = $_POST['author'];
            $pubdateval = $_POST['pubdate'];
            $isbnval = $_POST['isbn'];
            $priceval = $_POST['price'];

            //初始化domdocument类
            $xmldoc = new DOMDocument('1.0', "UTF-8");
            //载入XML文档
            $xmldoc->load("library.xml");
            //获取根节点
            $root = $xmldoc->getElementsByTagName("books")->item(0);
            //获取book节点
            $books = $root->getElementsByTagName("book");
            //查找我要删除的节点
            $id = $id - 1;
            $book = $books->item($id);

            //book元素的category属性修改
            $book->setAttribute('category', $category);

            $imgpic = $book->getElementsByTagName("imgpic")->item(0);
            $imgpic->nodeValue = $imgpicval;

            $title = $book->getElementsByTagName("title")->item(0);
            $title->nodeValue = $titleval;

            $author = $book->getElementsByTagName("author")->item(0);
            $author->nodeValue = $authorval;

            $pubdate = $book->getElementsByTagName("pubdate")->item(0);
            $pubdate->nodeValue = $pubdateval;

            $pubdate = $book->getElementsByTagName("isbn")->item(0);
            $pubdate->nodeValue = $pubdateval;

            $price = $book->getElementsByTagName("price")->item(0);
            $price->nodeValue = $priceval;

            $xmldoc->save("library.xml");
            echo "<script language='javascript'>alert('修改成功');location.href='index.php';</script>";
        }
    }

    /**
     * 写入XML文件
     * @param string $file
     * @param array $array
     * @param int $type
     * @return boolean
     */
    function xml_write(string $file, array $array, int $type = 0)
    {
        switch ($type) {
            case 0:
                $xml = new XMLWriter();
                $xml->openUri($file);
                $xml->setIndentString('  ');//设置缩进格式化使用的符号
                $xml->setIndent(true);
                $xml->startDocument('1.0', 'utf8');
                $xml->startElement('root');
                foreach ($array as $arr) {
                    $xml->startElement('child');
                    $keys = array_keys($arr);
                    foreach ($keys as $key) {
                        $xml->startElement($key);
                        $xml->text($arr[$key]);
                        $xml->endElement();
                    }
                    $xml->endElement();
                }
                $xml->endElement();
                $xml->endDocument();
                $xml->flush();
                break;
            case 1:
                //SimpleXML操作xml相对DOMDocument要简单许多，但函数功能较少，适合实现较简单的功能
                $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><root />');
                foreach ($array as $arr) {
                    $child = $xml->addChild('child');
                    $keys = array_keys($arr);
                    foreach ($keys as $key) {
                        $child->addChild($key, $arr[$key]);
                    }
                }
                $xml->asXml($file);//输出XML文件（没有格式化）
                break;
            case 2:
                //DOMDocument则提供了全面的操作xml函数和属性，适合实现复杂的xml操作
                $dom = new DOMDocument('1.0', 'utf8');
                $dom->formatOutput = true;
                $root = $dom->createElement('root');
                $dom->appendChild($root);
                foreach ($array as $arr) {
                    $period = $dom->createElement('child');
                    $root->appendChild($period);
                    $keys = array_keys($arr);
                    foreach ($keys as $key) {
                        $element = $dom->createElement($key);
                        $period->appendChild($element);
                        $text = $dom->createTextNode($arr[$key]);
                        $element->appendChild($text);
                    }
                }
                $dom->save($file);
                break;
        }
        return true;
    }

    /**
     * 读取XML文件
     * @param string $file
     * @param array $array
     * @param int $type
     * @return array
     */
    function xml_read($file, $array, $type = 0)
    {
        $arr = [];
        switch ($type) {
            case 0:
                // 大文件处理比其他两个好
                // XMLReader则是属于基于流的解析器，它不会一次把整个文档加载到内存中，而是每次分别读取其中的一个节点并允许实时与之交互，这种方式效率高，而且占内存少。
                $xml = new XMLReader();
                $xml->open($file);
                $count = 0;//记录数
                $name = '';
                while ($xml->read()) {
                    $n = $xml->name;
                    if ($xml->nodeType == XMLReader::ELEMENT) {
                        if ($n == 'child') {//开始下一条记录的读取
                            $count++;
                        } else if (in_array($n, $array)) {//记录需要获取文本值的标签名
                            $name = $n;
                        }
                    } else if ($xml->nodeType == XMLReader::TEXT) {
                        if (in_array($name, $array)) {
                            $arr[$count][$name] = $xml->value;
                        }
                    }
                }
                $xml->close();
                break;

            case 1:
                // SimpleXML和DOM扩展是属于基于树的解析器，把整个文档存储为树的数据结构中，需要把整个文档都加载到内存中才能工作，所以当处理大型XML文档的时候，性能会剧减。
                $values = simplexml_load_file($file);
                foreach ($values->children() as $value) {
                    $arr[] = get_object_vars($value);//获取对象全部属性，返回数组
                }
                break;

            case 2:
                $dom = new DOMDocument();
                $dom->load($file);
                $root = $dom->getElementsByTagName('child');
                foreach ($root as $key => $value) {
                    foreach ($array as $k) {
                        $node = $value->getElementsByTagName($k);
                        $arr[$key][$k] = $node->item(0)->nodeValue;
                    }
                }
                break;
        }
        return $arr;
    }

    public function read($content)
    {
        $p = xml_parser_create();
        xml_parse_into_struct($p, $content, $vals, $index);
        xml_parser_free($p);
    }
}